use poker_lib::Suit;

use crate::{
    card_weight::CardWeight,
    nil::NilCheck,
    round::Round,
    rule::IRule,
    table::Table,
    turn::{TurnHandPileState, TurnState},
    utils::Utils,
};

pub struct RuleCoverNilSolo;

impl IRule for RuleCoverNilSolo {
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let winning_card = &turn.winning_card().card;
        let suit = turn.leading_card().card.suit;

        if Utils::is_card_biggest_now(
            &turn.leading_card().card,
            &turn.play_cards_of_suit().get_suit_pocker_cards(suit),
            &_turn_state.history_suit_piles.get_suit_pocker_cards(suit),
        ) {
            Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
            return;
        }

        if let Some(highest) = Utils::get_highest_rank_from_pile(&_hand_pile.playable_pile) {
            if highest.get_number() < winning_card.get_number() {
                Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
                return;
            }
        }

        for item in &_hand_pile.playable_pile {
            let pile = &_hand_pile.pile_suit_group.get_suit_pocker_cards(suit);
            if _hand_pile.big_cards.contains(item) {
                CardWeight::add_card_x(item.get_number(), item, _card_weights);
            }
            CardWeight::add_card_y(item.get_number(), item, _card_weights);
            CardWeight::add_card_z(13 - pile.len() as i16, item, _card_weights);
        }
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let winning_card = &turn.winning_card().card;
        if let Some(card) =
            Utils::get_lowest_but_greater_than_win_card(winning_card, &_hand_pile.playable_pile)
        {
            if _turn_state.team_bt_delta > 0 {
                CardWeight::add_card_x(card.get_number(), &card, _card_weights);
            } else {
                Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
            }
        } else {
            Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
        }
    }

    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if !_hand_pile.big_cards.is_empty() {
            let mut flag = false;
            for suit in 0..=3 {
                let pile = Utils::get_cards_by_suit(&_hand_pile.big_cards, suit);
                if pile.is_empty() {
                    continue;
                }
                //比Q小的牌
                if let Some(lowest_card) = Utils::get_lowest_rank_card(&pile) {
                    if lowest_card.get_number() < 12 {
                        continue;
                    }
                }
                for item in &pile {
                    let pile2 = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item.suit);
                    let card_x = 13 - pile2.len() as i16;
                    CardWeight::add_card_x(card_x, item, _card_weights);
                    let card_y = item.get_number() as i16;
                    CardWeight::add_card_y(card_y, item, _card_weights);
                }
                flag = true;
            }
            if flag {
                return;
            }
        }

        if !_hand_pile.big_cards.is_empty() {
            for item4 in &_hand_pile.playable_pile {
                let pile3 = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item4.suit);
                let card_x2 = if _hand_pile.big_cards.contains(item4) {
                    98
                } else {
                    0
                };
                CardWeight::add_card_x(card_x2, item4, _card_weights);
                let card_y2 = pile3.len() as i16;
                CardWeight::add_card_y(card_y2, item4, _card_weights);
                let card_z2 = item4.get_number() as i16;
                CardWeight::add_card_z(card_z2, item4, _card_weights);
            }
            return;
        }

        for item5 in &_hand_pile.playable_pile {
            let pile4 = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item5.suit);
            let pile5 = &_turn_state
                .history_suit_piles
                .get_suit_pocker_cards(item5.suit);
            if pile5.len() >= 7
                && !Utils::check_pile_has_rank(pile5, 1)
                && !Utils::check_pile_has_rank(pile4, 1)
            {
                CardWeight::add_card_x(-90, item5, _card_weights);
            }
            let card_x3 = item5.get_number() as i16;
            CardWeight::add_card_x(card_x3, item5, _card_weights);
            let card_y3 = pile4.len() as i16;
            CardWeight::add_card_y(card_y3, item5, _card_weights);
        }
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let winning_card = &turn.winning_card().card;
        if _turn_state.team_bt_delta > 0 && _hand_pile.spades_pile.len() >= 2 {
            if !winning_card.is_trump_card() {
                CardWeight::add_playable_spades_card_weight(_hand_pile, _card_weights);
                return;
            }
            if let Some(card) =
                Utils::get_lowest_but_greater_than_win_card(winning_card, &_hand_pile.spades_pile)
            {
                CardWeight::add_card_x(card.get_number() as i16, &card, _card_weights);
                return;
            }
        }
        Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
    }
}

pub struct RuleAvoidBagsSolo;

impl IRule for RuleAvoidBagsSolo {
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let win_turn_card = turn.winning_card();
        let winning_card = &win_turn_card.card;
        if winning_card.is_trump_card() && !turn.leading_card().card.is_trump_card() {
            for item in &_hand_pile.playable_pile {
                CardWeight::add_card_x(item.get_number() as i16, item, _card_weights);
            }
            return;
        }
        if let Some(card) =
            Utils::get_highest_but_less_than_win_card(winning_card, &_hand_pile.playable_pile)
        {
            CardWeight::add_card_x(card.get_number() as i16, &card, _card_weights);
        } else {
            Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
        }
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        //solo 模式直接跟牌
        self.give_points_as_following_suit_by_player(
            _seat_id,
            _table,
            _round,
            _hand_pile,
            _turn_state,
            _card_weights,
        );
    }

    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        for item in &_hand_pile.playable_pile {
            if !item.is_trump_card()
                || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
            {
                let pile = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item.suit);
                let history_suit_piles = &_turn_state
                    .history_suit_piles
                    .get_suit_pocker_cards(item.suit);
                let card_x =
                    Utils::get_greeter_rank_but_hidden_card_nums(item, pile, history_suit_piles);
                CardWeight::add_card_x(card_x as i16, item, _card_weights);
                let card_y = 13 - pile.len() as i16;
                CardWeight::add_card_y(card_y, item, _card_weights);
            }
        }
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        if _hand_pile.playable_pile.len() != _hand_pile.spades_pile.len() {
            for item in &_hand_pile.playable_pile {
                let pile = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item.suit);
                if !item.is_trump_card() {
                    if _hand_pile.big_cards.contains(item) {
                        CardWeight::add_card_x(item.get_number(), item, _card_weights);
                    }
                    CardWeight::add_card_y(13 - pile.len() as i16, item, _card_weights);
                    CardWeight::add_card_z(item.get_number(), item, _card_weights);
                }
            }
            return;
        }
        let winning_card = &turn.winning_card().card;
        if winning_card.is_trump_card() {
            if let Some(card) =
                Utils::get_highest_but_less_than_win_card(winning_card, &_hand_pile.playable_pile)
            {
                CardWeight::add_card_x(card.get_number() as i16, &card, _card_weights);
                return;
            }
        }
        for item3 in &_hand_pile.playable_pile {
            CardWeight::add_card_x(item3.get_number() as i16, item3, _card_weights);
        }
    }
}
pub struct RuleAttackNilAndReachBidSolo;

impl IRule for RuleAttackNilAndReachBidSolo {
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        if !NilCheck::need_attack_nil_as_following(_round, _hand_pile, _turn_state, _card_weights) {
            RuleReachBidSolo.give_points_as_following_suit_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
            if let Some(opponent_player_id) =
                NilCheck::get_bid_nil_opponent_player(_round, _turn_state)
            {
                let opponent_player = _round.get_player_by_id(opponent_player_id);
                if !opponent_player.is_suit_voided(turn.leading_card().card.suit) {
                    if let Some(card) = Utils::get_lowest_rank_card(&_hand_pile.playable_pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                    }
                }
            }
        }
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        if !NilCheck::need_attack_nil_as_last(_round, _hand_pile, _turn_state, _card_weights) {
            RuleReachBidSolo.give_points_as_last_to_play_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
            if let Some(opponent_player_id) =
                NilCheck::get_bid_nil_opponent_player(_round, _turn_state)
            {
                let opponent_player = _round.get_player_by_id(opponent_player_id);
                if !opponent_player.is_suit_voided(turn.leading_card().card.suit) {
                    if let Some(card) = Utils::get_lowest_rank_card(&_hand_pile.playable_pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                    }
                }
            }
        }
    }

    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if !NilCheck::need_attack_nil_as_leader(_round, _hand_pile, _turn_state, _card_weights) {
            RuleReachBidSolo.give_points_as_leader_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
        }
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if NilCheck::need_attack_nil_when_voided_suit(
            _round,
            _hand_pile,
            _turn_state,
            _card_weights,
        ) {
            return;
        }
        RuleReachBidSolo.give_points_to_voided_suit_by_player(
            _seat_id,
            _table,
            _round,
            _hand_pile,
            _turn_state,
            _card_weights,
        );
        if let Some(opponent_player_id) = NilCheck::get_bid_nil_opponent_player(_round, _turn_state)
        {
            let opponent_player = _round.get_player_by_id(opponent_player_id);
            for suit_u8 in 0..=4u8 {
                let suit = Suit::from_u8(suit_u8).unwrap();
                if suit != Suit::Spade
                    && suit != Suit::Joker
                    && !opponent_player.is_suit_voided(suit)
                {
                    let pile = &_hand_pile.pile_suit_group.get_suit_pocker_cards(suit);
                    if pile.is_empty() {
                        continue;
                    }
                    if let Some(card) = Utils::get_lowest_rank_card(pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                    }
                }
            }
        }
    }
}
pub struct RuleAttackNilAndAvoidBagsSolo;

impl IRule for RuleAttackNilAndAvoidBagsSolo {
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        if !NilCheck::need_attack_nil_as_following(_round, _hand_pile, _turn_state, _card_weights) {
            RuleAvoidBagsSolo.give_points_as_following_suit_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
            if let Some(opponent_player_id) =
                NilCheck::get_bid_nil_opponent_player(_round, _turn_state)
            {
                let opponent_player = _round.get_player_by_id(opponent_player_id);
                if !opponent_player.is_suit_voided(turn.leading_card().card.suit) {
                    if let Some(card) = Utils::get_lowest_rank_card(&_hand_pile.playable_pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                    }
                }
            }
        }
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if !NilCheck::need_attack_nil_as_last(_round, _hand_pile, _turn_state, _card_weights) {
            RuleAvoidBagsSolo.give_points_as_last_to_play_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
            if let Some(opponent_player_id) =
                NilCheck::get_bid_nil_opponent_player(_round, _turn_state)
            {
                let turn = _round.cur_turn();
                let opponent_player = _round.get_player_by_id(opponent_player_id);
                if !opponent_player.is_suit_voided(turn.leading_card().card.suit) {
                    if let Some(card) = Utils::get_lowest_rank_card(&_hand_pile.playable_pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                    }
                }
            }
        }
    }

    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if !NilCheck::need_attack_nil_as_leader(_round, _hand_pile, _turn_state, _card_weights) {
            RuleAvoidBagsSolo.give_points_as_leader_by_player(
                _seat_id,
                _table,
                _round,
                _hand_pile,
                _turn_state,
                _card_weights,
            );
        }
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if NilCheck::need_attack_nil_when_voided_suit(
            _round,
            _hand_pile,
            _turn_state,
            _card_weights,
        ) {
            return;
        }
        RuleAvoidBagsSolo.give_points_to_voided_suit_by_player(
            _seat_id,
            _table,
            _round,
            _hand_pile,
            _turn_state,
            _card_weights,
        );
        if let Some(opponent_player_id) = NilCheck::get_bid_nil_opponent_player(_round, _turn_state)
        {
            for suit_u8 in 0..=3 {
                let suit = Suit::from_u8(suit_u8).unwrap();
                let opponent_player = _round.get_player_by_id(opponent_player_id);
                if suit != Suit::Spade
                    && suit != Suit::Joker
                    && !opponent_player.is_suit_voided(suit)
                {
                    let pile = &_hand_pile.pile_suit_group.get_suit_pocker_cards(suit);
                    if pile.is_empty() {
                        continue;
                    }
                    if let Some(card) = Utils::get_lowest_rank_card(pile) {
                        CardWeight::add_lowest_card_item(card, _card_weights);
                    }
                }
            }
        }
    }
}
pub struct RuleReachBidSolo;

impl IRule for RuleReachBidSolo {
    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        self.give_points_as_last_to_play_by_player(
            _seat_id,
            _table,
            _round,
            _hand_pile,
            _turn_state,
            _card_weights,
        );
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let winning_card = &turn.winning_card().card;
        let leading_card = &turn.leading_card().card;
        if leading_card.is_trump_card() {
            if let Some(card) =
                Utils::get_lowest_but_greater_than_win_card(winning_card, &_hand_pile.spades_pile)
            {
                CardWeight::add_card_x(card.get_number() as i16, &card, _card_weights);
                return;
            }
        } else {
            if winning_card.is_trump_card() {
                Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
                return;
            } else {
                if let Some(card) = Utils::get_lowest_but_greater_than_win_card(
                    winning_card,
                    &_hand_pile.playable_pile,
                ) {
                    CardWeight::add_card_x(card.get_number() as i16, &card, _card_weights);
                    return;
                }
            }
        }
        Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
    }

    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        if _hand_pile.spades_pile.len() >= 6 {
            for item in &_hand_pile.spades_pile {
                if _hand_pile.big_cards.contains(item) {
                    CardWeight::add_card_x(item.get_number(), item, _card_weights);
                }
                CardWeight::add_card_y((14 - item.get_number()) as i16, item, _card_weights);
            }
            return;
        }
        let player = _round.get_player_by_id(_turn_state.partner_player_id);
        let player2 = _round.get_player_by_id(_turn_state.pre_player_id);
        let player3 = _round.get_player_by_id(_turn_state.next_player_id);
        if Utils::check_pile_has_rank(&_hand_pile.playable_pile, 1) {
            let mut flag = false;
            for item2 in &_hand_pile.playable_pile {
                let suit = item2.suit;
                if !item2.is_trump_card()
                    || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
                {
                    let pile = &_turn_state.history_suit_piles.get_suit_pocker_cards(suit);
                    if item2.get_number() == 14 && pile.is_empty() {
                        let pile2 = &_hand_pile.pile_suit_group.get_suit_pocker_cards(suit);
                        let card_x = item2.get_number() as i16;
                        CardWeight::add_card_x(card_x, item2, _card_weights);
                        let card_y = 13 - pile2.len() as i16;
                        CardWeight::add_card_y(card_y, item2, _card_weights);
                        flag = true;
                    }
                }
            }
            if flag {
                return;
            }
        }
        //出别人空花色的牌
        if player.voided_suits.len() > 0
            || player2.voided_suits.len() > 0
            || player3.voided_suits.len() > 0
        {
            let mut list = Vec::new();
            for suit_u8 in 0..=3u8 {
                let suit = Suit::from_u8(suit_u8).unwrap();
                if player.voided_suits.contains(&suit)
                    || player2.voided_suits.contains(&suit)
                    || player3.voided_suits.contains(&suit)
                {
                    list.push(suit);
                }
            }
            if Utils::has_suit_poker_in_other_voided_suit_list(&_hand_pile.playable_pile, &list) {
                if list.len() < 3 {
                    let mut flag2 = false;
                    for item5 in &_hand_pile.big_cards {
                        if !list.contains(&item5.suit) {
                            flag2 = true;
                            break;
                        }
                    }
                    if flag2 {
                        for item6 in &_hand_pile.big_cards {
                            let item6_suit = item6.suit;
                            if !item6.is_trump_card()
                                || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
                            {
                                let pile5 =
                                    &_hand_pile.pile_suit_group.get_suit_pocker_cards(item6_suit);
                                let card_x3 = if !list.contains(&item6.suit) { 100 } else { 0 };
                                CardWeight::add_card_x(card_x3, item6, _card_weights);
                                let card_x3 = 13 - pile5.len() as i16;
                                CardWeight::add_card_y(card_x3, item6, _card_weights);
                                let card_x3 = item6.get_number() as i16;
                                CardWeight::add_card_z(card_x3, item6, _card_weights);
                            }
                        }
                        return;
                    }
                    if Utils::has_suit_poker_in_other_voided_suit_list(
                        &_hand_pile.playable_pile,
                        &list,
                    ) {
                        for item7 in &_hand_pile.playable_pile {
                            let item_suit = item7.suit;
                            if !item7.is_trump_card()
                                || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
                            {
                                let pile6 =
                                    &_hand_pile.pile_suit_group.get_suit_pocker_cards(item_suit);
                                let card_x4 = if !list.contains(&item7.suit) { 100 } else { 0 };
                                CardWeight::add_card_x(card_x4, item7, _card_weights);
                                let card_x4 = 13 - pile6.len() as i16;
                                CardWeight::add_card_y(card_x4, item7, _card_weights);
                                let card_x4 = 14 - item7.get_number() as i16;
                                CardWeight::add_card_z(card_x4, item7, _card_weights);
                            }
                        }
                        return;
                    }
                }
                for item8 in &_hand_pile.playable_pile {
                    let item_suit = item8.suit;
                    if !item8.is_trump_card()
                        || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
                    {
                        let pile7 = &_hand_pile.pile_suit_group.get_suit_pocker_cards(item_suit);
                        let card_x5 = if list.contains(&item_suit) { 100 } else { 0 };
                        CardWeight::add_card_x(card_x5, item8, _card_weights);
                        let card_x5 = 13 - pile7.len() as i16;
                        CardWeight::add_card_y(card_x5, item8, _card_weights);
                        let card_x5 = 14 - item8.get_number() as i16;
                        CardWeight::add_card_z(card_x5, item8, _card_weights);
                    }
                }
                return;
            }
        }
        CardWeight::add_playable_card_weight(_hand_pile, _card_weights);
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        let turn = _round.cur_turn();
        let winning_card = &turn.winning_card().card;
        let leading_card = &turn.leading_card().card;
        if !leading_card.is_trump_card() && _hand_pile.spades_pile.len() > 0 {
            if !winning_card.is_trump_card() {
                CardWeight::add_playable_spades_card_weight(_hand_pile, _card_weights);
                return;
            }
            if let Some(card) =
                Utils::get_lowest_but_greater_than_win_card(winning_card, &_hand_pile.spades_pile)
            {
                CardWeight::add_card_x(card.get_number() as i16, &card, _card_weights);
                return;
            }
        }
        Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
    }
}
pub struct RuleAttackBagSolo;
impl IRule for RuleAttackBagSolo {
    fn give_points_as_leader_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
    }

    fn give_points_as_last_to_play_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
    }

    fn give_points_as_following_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
    }

    fn give_points_to_voided_suit_by_player(
        &mut self,
        _seat_id: usize,
        _table: &Table,
        _round: &Round,
        _hand_pile: &TurnHandPileState,
        _turn_state: &TurnState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        Utils::compute_lower_rank_and_most_card_num(_hand_pile, _card_weights);
    }
}
